(function (factory) {
    "use strict";
    if (typeof define === 'function' && define.amd) {
        // AMD
        define(['jquery'], function ($) {
            return factory($, window, document);
        });
    } else if (typeof exports === 'object') {
        // CommonJS
        module.exports = function (root, $) {
            if (!root) {
                // CommonJS environments without a window global must pass a
                // root. This will give an error otherwise
                root = window;
            }

            if (!$) {
                $ = typeof window !== 'undefined' ? // jQuery's factory checks
                    // for a global window
                    require('jquery') : require('jquery')(root);
            }

            return factory($, root, root.document);
        };
    } else {
        // Browser
        factory(jQuery, window, document);
    }
}
(function ($, window, document, undefined) {
    "use strict";
    var pagination, defaults = {
        url: '',
        async: false,
        hasCk: false,
        column: []
    }, pre_data = '<a  data-dt-idx="1" class="pre" href="javascript:void(0)">&laquo;</a>', next = '<a  data-dt-idx="totalPage" class="next" href="javascript:void(0)">&raquo;</a>', li_prefix = '<li>', li_prefix_disable = '<li class="disabled">', li_suffix = '</li>', li_active = '<li class="active">';

    $.fn.pagination = pagination;
    pagination = function (obj, opt) {
        this.target = obj;
        this.page = {
            pageNo: 1,
            pageSize: 5,
            totalCount: 0,
            totalPages: 0,
            first: 0,
            result: []
        },
            this.param = {};

        this.id = obj.attr('id');
        this.setting = $.extend({}, obj.defaults, opt);

        this.init();

        this.tbody = obj.find('tbody');
        this.pagination_info = $(obj.parent().parent().find(
            '#pagination_info')[0]);

        this.pagination_bar = $(obj.parent().parent().find(
            '#pagination_bar')[0]);
    };

    function _init() {
        var obj = this, column = obj.setting.column;
        if (!column || column.length < 1) {
            console.log('列不能为空');
            return;
        }
        var size = column.length, h = '', section, p;

        // parent
        obj.target.wrap('<section><div class="row"></div></section>');
        // thead
        h += '<thead>';
        h += '<tr>';
        $.each(column, function (i, n) {
            h += '<th>' + n.name + '</th>';
        });
        h += '</tr>';
        h += '<tbody></tbody>';
        obj.target.append(h);
        // pagination
        section = obj.target.parent().parent();

        p = '<div class="row">';
        // p += '<div class="col-sm-5">';
        p += '<div id="pagination_info" class="dataTables_info pull-left" role="status" aria-live="polite">0 到 0 总计 0 条, 共 0 页</div>';
        // p += '</div><div class="col-sm-7">';
        p += '<ul id="pagination_bar" class="pagination pull-right" style="margin: 2px 0;">';
        p += li_prefix_disable + pre_data + li_suffix;
        p += li_prefix_disable + next + li_suffix;
        p += '</ul></div>';
        // p += '</div>';
        section.append(p);
    }

    function _loadData() {
        var obj = this;
        if (!obj.setting.url) {
            console.log('请求地址不能为空!');
            return;
        }
        obj.param.pageNo = obj.page.pageNo;
        obj.param.pageSize = obj.page.pageSize;
        $.ajax({
            url: obj.setting.url,
            async: obj.setting.async,
            type: 'post',
            data: obj.param,
            dataType: 'json',
            success: function (data) {
                _parseData(obj, data);
            },
            error: function () {
                alert('获取数据失败!');
            }
        });
    }

    function _generatedData(column, data, c) {
        var h = '', p, v, x;
        $
            .each(
            data,
            function (i, n) {
                h += '<tr>';
                $
                    .each(
                    column,
                    function (j, m) {
                        v = '';
                        p = m.property;
                        for (x in n) {
                            if (x == p) {
                                v = n[x];
                                break;
                            }
                        }
                        if (m.formatter) {
                            v = m.formatter(i,
                                v, n,
                                field, j);
                        }
                        h += '<td>';
                        if (j == 0 && c) {
                            h += '<input type="checkbox" class="checkbox" data-index="' + i + '" value="'
                                + v + '">';
                        } else {
                            h += v;
                        }
                        h += '</td>';
                    });
                h += '</tr>';
            });
        return h;
    }

    function _generatedPaginationBar(totalPages, pageNo) {
        var g;
        if (totalPages == 1) {
            g = li_prefix_disable + pre_data + li_suffix;
            g += li_prefix_disable;
            g += '<a href="javascript:void(0);">1</a>';
            g += li_suffix;
            g += li_prefix_disable + next + li_suffix;
        } else {
            if (pageNo == 1) {
                g = li_prefix_disable + pre_data + li_suffix;
            } else {
                g = li_prefix + pre_data + li_suffix;
            }
            var haspre, hassuff, pre, suff;
            if (totalPages < 10) {
                // less 11
                haspre = false;
                hassuff = false;
                pre = 1;
                suff = totalPages;
            } else {
                // gt 10
                if (pageNo <= 5) {
                    haspre = false;
                    hassuff = true;
                    pre = 1;
                    suff = 7;
                } else if (pageNo < totalPages - 3) {
                    haspre = true;
                    hassuff = true;
                    pre = pageNo - 2;
                    suff = pageNo + 2;
                    if (totalPages - suff == 2) {
                        suff++;
                        hassuff = false;
                    }
                } else {
                    haspre = true;
                    hassuff = false;
                    pre = totalPages - 6;
                    suff = totalPages;
                }
            }
            if (haspre) {

                if (pageNo == 1) {
                    g += li_active;
                } else {
                    g += li_prefix;
                }
                g += '<a data-dt-idx="1" href="javascript:void(0);">1</a>';
                g += li_suffix;
                g += li_suffix;
                g += li_prefix;
                g += '<span>...</span>';
                g += li_suffix;
            }
            for (var i = pre; i <= suff; i++) {
                if (pageNo == i) {
                    g += li_active;
                } else {
                    g += li_prefix;
                }
                g += '<a data-dt-idx="' + i
                    + '" href="javascript:void(0);">' + i + '</a>';
                g += li_suffix;
            }
            if (hassuff) {
                g += li_suffix;
                g += li_prefix;
                g += '<span>...</span>';
                g += li_suffix;
                if (pageNo == totalPages) {
                    g += li_active;
                } else {
                    g += li_prefix;
                }
                g += '<a data-dt-idx="' + totalPages
                    + '" href="javascript:void(0);">' + totalPages
                    + '</a>';

            }
            if (pageNo == totalPages) {
                g += li_prefix_disable
                    + next.replace(/totalPage/, totalPages)
                    + li_suffix;
            } else {
                g += li_prefix + next.replace(/totalPage/, totalPages)
                    + li_suffix;
            }
        }
        return g;
    }

    function _generatedPaginationInfo(first, pageSize, totalCount, totalPages) {
        return first + ' 到 ' + (first + pageSize - 1) + ' 总计 '
            + totalCount + ' 条, 共 ' + totalPages + ' 页';
    }

    function _parseData(obj, data) {
        var a, column = obj.setting.column, h, c = obj.setting.hasCk, g, f, page = obj.page;
        obj.page.result = data.result;
        obj.page.totalCount = data.totalCount;
        obj.page.totalPages = data.totalPages;
        // data
        h = _generatedData(column, data.result, c);
        obj.tbody.html(h);
        // 判断总数是否变化
        // pagination_bar
        if (data.totalCount > 0) {
            g = _generatedPaginationBar(data.totalPages, data.pageNo);
            obj.pagination_bar.html(g);
            //bind fn
            $.each(obj.pagination_bar.find('li'), function (i, n) {
                $(n).bind('click', function () {
                    a = $($(n).find('a')[0]);
                    obj.pagenationClick(a.attr('data-dt-idx'));
                });
            });
        }
        //pagination_info
        f = _generatedPaginationInfo(data.first, data.result.length, data.totalCount,
            data.totalPages);
        obj.pagination_info.html(f);
        obj.page = data;
    }

    function _pagenationClick(p) {
        if (p != this.page.pageNo) {
            this.page.pageNo = p;
            this.loadData();
        }
    }

    function _getChecked() {
        var obj = this, ck = this.target.find(":checkbox:checked"), arr = [], index;
        $.each(ck, function (i, n) {
            index = $(n).attr("data-index");
            arr.push(obj.page.result[index]);
        });
        return arr;
    }

    function _getCheckedValue() {
        var obj = this, ck = this.target.find(":checkbox:checked"), arr = [];
        $.each(ck, function (i, n) {
            arr.push($(n).val());
        });
        return arr;
    }

    $.extend(pagination.prototype, {
        init: _init,
        loadData: _loadData,
        pagenationClick: _pagenationClick,
        getChecked: _getChecked,
        getCheckedValue: _getCheckedValue
    });

    $.fn.pagination = function (opts) {
        return new pagination(this, opts);
    };
    return $.fn.pagination;
}));
